package cn.demoncat.test.neo.node;

import cn.demoncat.util.lang.CollectionUtil;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import java.util.List;

/**
 * 节点实体
 *
 * 特点：【A】 -关系-> B
 */
@NodeEntity("RUser")
public class RUserNode {

    private Long id;
    private String name;

    /**
     * 直接关系（无属性）：关系类型
     *
     * 1.保存节点：同时保存关联的节点、关系（只有id属性）
     * 2.查询节点：同时返回关联的节点
     */
    @Relationship("FRIEND")
    private List<RUserNode> friends;

    /**
     * 间接关系（有属性）：关系类型
     *
     * 1、保存关系，同时保存节点
     * 2、查询节点：同时返回关系
     * 3、防止JSON序列化时循环引用导致StackOverflowError，需要在序列化前置null关系实体或节点实体(根据查询主表而定)
     */
    @Relationship("USER_FOOD")
    private List<RUserRelation> foods;

    /**
     * JSON序列化前预处理
     *
     * 1、查询 RUserNode
     * 2、RUserNode.foods 持有 RUserNode 自身，这将导致JSON序列化时StackOverflowError
     * 3、预处理：置null关系实体(RUserNode.foods.RUserNode)
     *
     * @param list 查询结果
     * @return 处理后
     */
    public static Iterable<RUserNode> beforeJson(Iterable<RUserNode> list){
        if (list != null) {
            list.forEach(o -> {
                if (CollectionUtil.isNotEmpty(o.getFoods())) {
                    o.getFoods().stream().forEach(f -> {
                        f.setUser(null);
                    });
                }
            });
        }
        return list;
    }

    /**
     * JSON序列化前预处理
     *
     * 1、查询 RUserNode
     * 2、RUserNode.foods 持有 RUserNode 自身，这将导致JSON序列化时StackOverflowError
     * 3、预处理：置null关系实体(RUserNode.foods.RUserNode)
     *
     * @param node 查询结果
     * @return 处理后
     */
    public static RUserNode beforeJson(RUserNode node){
        if (node != null) {
            if (CollectionUtil.isNotEmpty(node.getFoods())) {
                node.getFoods().stream().forEach(f -> {
                    f.setUser(null);
                });
            }
        }
        return node;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<RUserNode> getFriends() {
        return friends;
    }

    public void setFriends(List<RUserNode> friends) {
        this.friends = friends;
    }

    public List<RUserRelation> getFoods() {
        return foods;
    }

    public void setFoods(List<RUserRelation> foods) {
        this.foods = foods;
    }
}
